home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / yase.arc / EDIT3.ASM < prev    next >
Assembly Source File  |  1986-12-13  |  15KB  |  448 lines

  1. ******************************************************************
  2. * COPYRIGHT (C) 1986 by Donald Krantz and James Stanley
  3. * - Note: This is a real, live, actual, registered copyright,
  4. *   and should be treated as such. This source code is from
  5. *   the book "68000 Assembly Language", Krantz and Stanley,
  6. *   Addison-Wesley Publishing Company, Reading, MA, 1986.
  7. *   Permission granted by the authors for non-commercial use
  8. *   in programs released to the public domain, as long as this
  9. *   copyright notice remains attached and visible.
  10. *
  11. *****************************************************************
  12. * Editor Dispatcher
  13.  
  14.     xref    prtscr,stats,_getkey,sync_curs,case,cursor
  15.     xref    _keyhit,group_1,group_2,group_4,refind,errors
  16.     xref    prompt
  17.     xdef    up,down,right,left,down_page,up_page,del_left
  18.     xdef    toggle,eol,sol,dirty
  19.     xdef    edit
  20.  
  21. #edit.h
  22. #cursor.h
  23.  
  24. ****************************************************************
  25. * EDIT - Main editor dispatcher and executive.
  26. edit:
  27.     bsr    _keyhit        * see if we're busy
  28.     tst.w    d0        * d0 is nonzero if we're busy
  29.     bne    sk1exec        * we skip refresh if busy
  30.     bsr    align_scr    * make sure cursor's on screen
  31.     bsr    prtscr        * Print current buffer
  32.     bsr    stats        * Print editing stats
  33.     move.w    ed_err(a5),d0    * Get edit error flag
  34.     ext.l    d0        * make into longword
  35.     lsl.l    #2,d0        * multiply by four
  36.     move.l    #errors,a0    * get error message lookup table
  37.     add.l    d0,a0        * get offset
  38.     move.l    (a0),a0        * get error string address
  39.     bsr    prompt        * output message (or blank old)
  40.     clr.w    ed_err(a5)    * mark "no errors"
  41. sk1exec:
  42.     move.w    scr_row(a5),-(a7) put cursor where it belongs
  43.     move.w    scr_col(a5),-(a7)
  44.     bsr    cursor
  45.     addq.l    #4,a7        * adjust stack
  46.     bsr    sync_curs    * Put cursor where it belongs
  47.     bsr    _getkey        * get input
  48.     ext.w    d0        * make into a word
  49.     move.l    #dispatch,a0    * load up case table
  50.     bsr    case        * perform required operation
  51.  
  52.     bra    edit        * repeat
  53. *****************************************************************
  54. * Top Level Editor Dispatch Table
  55. dispatch:
  56.     dc.w    23        * Number of valid options
  57.     dc.w    tab        * Tab
  58.     dc.l    in_chr
  59.     dc.w    0        * PC cursor key prefix
  60.     dc.l    group_4
  61.     dc.w    c_up        * Cursor up one line
  62.     dc.l    up
  63.     dc.w    c_down        * Cursor down one line
  64.     dc.l    down
  65.     dc.w    c_right        * Cursor one char right
  66.     dc.l    right
  67.     dc.w    c_left        * Cursor one char left
  68.     dc.l    left
  69.     dc.w    c_w_right    * Cursor one word right
  70.     dc.l    w_right
  71.     dc.w    c_w_left    * Cursor one word left
  72.     dc.l    w_left
  73.     dc.w    return        * Return Key
  74.     dc.l    ret
  75.     dc.w    backsp        * Backspace Key
  76.     dc.l    left
  77.     dc.w    left_del    * Left Delete Character
  78.     dc.l    del_left
  79.     dc.w    right_del    * Right Delete Character
  80.     dc.l    del_right
  81.     dc.w    lit_prefix    * Literal Insertion Prefix
  82.     dc.l    prefix
  83.     dc.w    word_del    * Right Delete Word 
  84.     dc.l    del_word
  85.     dc.w    group1        * Group 1 Commands prefix
  86.     dc.l    group_1    
  87.     dc.w    group2        * Group 2 Commands prefix
  88.     dc.l    group_2
  89.     dc.w    group3        * Group 3 Commands prefix
  90.     dc.l    group_3
  91.     dc.w    line_del    * Delete line key
  92.     dc.l    del_line
  93.     dc.w    page_up        * Page Up key
  94.     dc.l    up_page
  95.     dc.w    page_down    * Page Down key
  96.     dc.l    down_page
  97.     dc.w    repeat        * Repeat Find key
  98.     dc.l    refind
  99.     dc.w    insert_key    * Insert Toggle Key
  100.     dc.l    toggle    
  101.     dc.w    ins_line    * Insert Line key
  102.     dc.l    line_ins
  103.     dc.l    ins_chr        * default - insert character
  104. *****************************************************************
  105. * GROUP_3 - group 3 (window) commands
  106. group_3:
  107.     move.l    #-1,d0        * Set "continue" flag
  108.     addq.l    #4,a7        * lift one return address
  109.     rts            * return to caller of "edit"
  110. *****************************************************************
  111. * RIGHT - Moves cursor right. Returns byte moved in D0.
  112. right:
  113.     clr.w    d0        * setup fake return value
  114.     move.l    e_gap(a5),a0    * check if we can move left
  115.     cmp.l    e_buf(a5),a0    * we look at the end of buffer
  116.     bgt    sk0_rt        * jump if we can't move
  117.     move.l    b_gap(a5),a1    * get destination for char
  118.     move.b    (a0),d0        * save the byte to return it
  119.     cmp.b    #10,(a0)    * check for line crossing
  120.     bne    sk1_rt        * skip if not line crossing
  121.     addq.w    #1,log_lin(a5)    * add one to line count
  122. sk1_rt:
  123.     move.b    (a0)+,(a1)+    * move the byte across gap
  124.     addq.l    #1,e_gap(a5)    * move end pointer
  125.     addq.l    #1,b_gap(a5)    * move start pointer
  126. sk0_rt:
  127.     rts
  128. *****************************************************************
  129. * LEFT - moves cursor left. Returns byte moved in D0.
  130. left:
  131.     clr.w    d0        * setup fake return value
  132.     move.l    b_gap(a5),a0    * check if we can move right
  133.     cmp.l    b_buf(a5),a0    * we look at the start of buffer
  134.     ble    sk0_lf        * jump if we can't move
  135.     move.l    e_gap(a5),a1    * get destination for char
  136.     move.b    -(a0),-(a1)    * move the byte across gap
  137.     move.b    (a1),d0        * save the byte to return it
  138.     cmp.b    #10,(a1)    * check for line crossing
  139.     bne    sk1_lf        * jump if not line crossing
  140.     subq.w    #1,log_lin(a5)    * bump down current line counter
  141. sk1_lf:
  142.     subq.l    #1,e_gap(a5)    * move end pointer
  143.     subq.l    #1,b_gap(a5)    * move start pointer
  144. sk0_lf:
  145.     rts
  146. *****************************************************************
  147. * UP - moves cursor up one line 
  148. up:
  149.     bsr    sol        * move to start of this line
  150.     bsr    left        * move back over newline
  151.     bsr    sol        * move to start of this line
  152.     bsr    outline        * put cursor out into line
  153.     rts
  154. *****************************************************************
  155. * DOWN - moves cursor down one line 
  156. down:
  157.     bsr    eol        * move to end of line
  158.     bsr    right        * jump over newline
  159.     bsr    outline        * put cursor out into line
  160.     rts
  161. *****************************************************************
  162. * W_RIGHT - Moves the cursor one word right
  163. w_right:
  164.     bsr    right        * start right
  165.     tst.b    d0        * look for end-of-file
  166.     beq    sk0_wr        * outta here if end of file
  167.     bsr    isdelim     * look for delimiter
  168.     tst.b    d0        * check return value
  169.     beq    w_right        * loop until we find delimiter
  170. lp0_wr:
  171.     bsr    right        * start right
  172.     tst.b    d0        * look for end-of-file
  173.     beq    sk0_wr        * outta here if end of file
  174.     bsr    isdelim     * look for delimiter
  175.     tst.b    d0        * check return value
  176.     bne    lp0_wr        * loop until we finish delimiters
  177.     bsr    left        * back off one
  178. sk0_wr:
  179.     rts
  180. *****************************************************************
  181. * W_LEFT - move the cursor one word to the left
  182. w_left:
  183.     bsr    left        * start left
  184.     tst.b    d0        * look for start-of-file
  185.     beq    sk0_wl        * outta here if start of file
  186.     bsr    isdelim     * look for delimiter
  187.     tst.b    d0        * check return value
  188.     bne    w_left        * loop while no delimiter
  189. lp0_wl:
  190.     bsr    left        * start left
  191.     tst.b    d0        * look for start-of-file
  192.     beq    sk0_wl        * outta here if start of file
  193.     bsr    isdelim     * look for delimiter
  194.     tst.b    d0        * check return value
  195.     beq    lp0_wl        * loop until we hit delimiters
  196.     bsr    right        * back off one
  197. sk0_wl:
  198.     rts
  199. *****************************************************************
  200. * UP_PAGE - moves cursor up one page
  201. up_page:
  202.     move.w    w_rows(a5),d1    * calculate number of lines
  203.     subq.w    #2,d1        * leave two rows for context
  204.     bgt    sk0_up        * check if we still have some
  205.     clr.w    d1        * we need at least one...
  206. sk0_up:
  207.     bsr    sol        * move to start of this line
  208.     bsr    left        * back up over newline
  209.     tst.w    d0        * check for top of file
  210.     beq    sk1_up        * break out if top of file
  211.     dbra    d1,sk0_up    * loop 'lines' times
  212.     bsr    right        * move over current newline
  213. sk1_up:    
  214.     bsr    outline        * move cursor out into line
  215.     rts
  216. *****************************************************************
  217. * DOWN_PAGE - moves cursor down one page
  218. down_page:
  219.     move.w    w_rows(a5),d1    * calculate number of lines
  220.     subq.w    #3,d1        * leave two rows for context
  221.     bgt    sk0_dn        * check if we still have some
  222.     move.w    #0,d1        * we need at least one...
  223. sk0_dn:
  224.     bsr    eol        * move to end of this line
  225.     bsr    right        * skip over newline
  226.     dbra    d1,sk0_dn    * loop 'lines' times
  227.     bsr    sol        * move to start of this line
  228.     bsr    outline        * move cursor out into line
  229.     rts
  230. *****************************************************************
  231. * DEL_RIGHT - delete one character to the right
  232. del_right:
  233.     bsr    right        * try to move right
  234.     tst.b    d0        * is there anything there?
  235.     beq    sk0dr        * jump if not
  236.     subq.l    #1,b_gap(a5)    * delete character
  237.     bsr    dirty        * set modified flags
  238. sk0dr:
  239.     rts
  240. *****************************************************************
  241. * DEL_LEFT - delete one character to the left
  242. del_left:
  243.     bsr    left        * try to move left
  244.     tst.b    d0        * is there anything there?
  245.     beq    sk0dl        * jump if not
  246.     addq.l    #1,e_gap(a5)    * delete character
  247.     bsr    dirty        * set modified flags
  248. sk0dl:
  249.     rts
  250. *****************************************************************
  251. * DEL_LINE - deletes line that cursor is on
  252. del_line:
  253.     bsr    sol        * move to start of this line
  254.     move.l    b_gap(a5),-(a7)    * save gap start address
  255.     bsr    eol        * move to end of this line
  256.     bsr    right        * and one more for newline
  257.     cmp.b    #10,d0        * make sure we got a newline
  258.     bne    sk0ld        * jump if not
  259.     subq.w    #1,log_lin(a5)    * adjust line count
  260. sk0ld:
  261.     move.l    (a7)+,b_gap(a5)    * poof! line's gone.
  262.     bsr    dirty        * set modified flags
  263.     rts
  264. *****************************************************************
  265. del_word:
  266.     move.l    b_gap(a5),-(a7)    * Save gap pointer
  267.     bsr    w_right        * move cursor one word right
  268.     move.l    (a7)+,b_gap(a5)    * restore pointer, word vanishes
  269.     bsr    dirty        * set modified flags
  270.     rts
  271. *****************************************************************
  272. * PREFIX - Allows human to inser next char typed as literal
  273. prefix:
  274.     bsr    _getkey        * take the next keystroke as-is
  275.     bra    in_chr        * insert whatever comes in
  276. *****************************************************************
  277. ret:
  278.     move.b    #10,d0        * load up a newline
  279.     bra    in_chr        * go insert it
  280. *****************************************************************
  281. toggle:
  282.     not.w    insert(a5)    * complement insert toggle
  283.     rts
  284. *****************************************************************
  285. line_ins:
  286.     move.l    e_gap(a5),a0    * get begin gap pointer
  287.     cmp.l    b_gap(a5),a0    * see if there's room
  288.     ble    sk0_lns        * jump if no room
  289.     move.b    #10,-(a0)    * put in newline
  290.     subq.l    #1,e_gap(a5)    * adjust end pointer
  291.     bsr    dirty        * set modified flags
  292.     rts            * exit
  293. sk0_lns:
  294.     move.w    #2,ed_err(a5)    * error 2 - no more room
  295.     rts
  296. *****************************************************************
  297. ins_chr:
  298.     cmp.b    #$20,d0        * check if char out of range
  299.     blt    sk1_ins        * if out, goto error
  300. in_chr:
  301.     tst.w    insert(a5)    * is insert toggle on?
  302.     bne    sk2_ins        * jump if yes
  303.     move.l    e_gap(a5),a0    * get end-of-gap address
  304.     cmp.l    e_buf(a5),a0    * check if at end of buffer
  305.     bgt    sk2_ins        * yes, go insert
  306.     cmp.b    #10,(a0)    * see if next char is newline
  307.     beq    sk2_ins        * yes, go insert
  308.     move.l    b_gap(a5),a0    * we need to replace...
  309.     move.b    d0,(a0)        * emplace new character
  310.     addq.l    #1,b_gap(a5)    * move begin gap pointer
  311.     addq.l    #1,e_gap(a5)    * move end gap pointer
  312.     bra    sk4_ins        * exit
  313. sk2_ins:
  314.     move.l    b_gap(a5),a0    * get begin gap pointer
  315.     cmp.l    e_gap(a5),a0    * look see if there's room
  316.     bge    sk3_ins        * jump if no room
  317.     move.b    d0,(a0)        * insert character
  318.     addq.l    #1,b_gap(a5)    * move gap pointer
  319.     cmp.b    #10,d0        * check for newline
  320.     bne    sk4_ins        * skip if not
  321.     addq.w    #1,log_lin(a5)    * increment logical line count
  322. sk4_ins:
  323.     bsr    dirty        * set modified flags
  324.     rts            * That's it.
  325. sk1_ins:
  326.     move.w    #1,ed_err(a5)    * error #1 - char out of range
  327.     rts
  328. sk3_ins:
  329.     move.w    #2,ed_err(a5)    * error #2 - no room
  330.     rts
  331. *****************************************************************
  332. * ISDELIM - returns TRUE if char in D0 matches delimiter list
  333. isdelim:
  334.     move.l    #delim,a0    * get delimiter list address
  335.     move.w    #d_cnt,d1    * get delimiter count
  336. lp0_dm:
  337.     cmp.b    (a0)+,d0    * look for a match
  338.     beq    d_true        * found one, jump out
  339.     dbra    d1,lp0_dm    * check all cases
  340.     clr.w    d0        * return FALSE
  341.     rts
  342. d_true:
  343.     move.w    #$FFFF,d0    * return TRUE
  344.     rts
  345.  
  346. delim:    dc.b    9,10,' ,.-+/><()'
  347. d_cnt    equ    *-delim
  348.     dc.w    0
  349. *****************************************************************
  350. * SOL - moves cursor to start of line
  351. sol:
  352.     bsr    left        * try one char back
  353.     tst.b    d0        * check if at top of file
  354.     beq    sk0sol        * jump out if at top of file
  355.     cmp.b    #10,d0        * is this a newline?
  356.     bne    sol        * back up to start of this line
  357.     bsr    right        * re-adjust cursor
  358. sk0sol:
  359.     rts
  360. *****************************************************************
  361. * EOL - moves cursor to end of line
  362. eol:
  363.     bsr    right        * try one char forward
  364.     tst.b    d0        * check if at end of file
  365.     beq    sk0eol        * jump out if at end of file
  366.     cmp.b    #10,d0        * check for newline
  367.     bne    eol        * loop if not newline
  368.     bsr    left        * put cursor behind newline
  369. sk0eol:
  370.     rts    
  371. *****************************************************************
  372. * OUTLINE - moves cursor to current logical column
  373. outline:
  374.     clr.w    d2        * d2 is column accumulator
  375. lp0_ol:
  376.     bsr    right        * try to move right
  377.     tst.b    d0        * check if end-of file
  378.     beq    sk1_ol        * exit if end-of-file
  379.     cmp.b    #10,d0        * check for end of line
  380.     beq    sk0_ol        * done if end-of-line
  381.     addq.w    #1,d2        * start with one column
  382.     cmp.b    #$20,d0        * see if control char
  383.     bge    sk2_ol        * if not, we're done with char
  384.     cmp.b    #tab,d0        * is char a tab?
  385.     beq    sk3_ol        * jump if tab
  386.     subq.l    #1,d2        * take away column for ctrl char
  387.     bra    sk2_ol        * make loop test
  388. sk3_ol:
  389.     move.w    d2,d0        * make a copy of column count
  390.     and.w    #$0007,d0    * check for correct tab column
  391.     beq    sk2_ol        * if so, make loop test
  392.     addq.w    #1,d2        * otherwise, add one space to col
  393.     bra    sk3_ol        * and keep expanding tab
  394. sk2_ol:
  395.     cmp.w    log_col(a5),d2    * are we far enough out?
  396.     ble    lp0_ol        * no, keep trying
  397. sk0_ol:
  398.     bsr    left        * back up to correct position
  399. sk1_ol:
  400.     rts 
  401. *****************************************************************
  402. * ALIGN_SCR - Handles vertical cursor alignment. Puts the cursor
  403. * on the screen if it's off.
  404. align_scr:
  405.     move.l    b_gap(a5),a0    * Get start of gap (cursor loc.)
  406.     cmp.l    top_lef(a5),a0    * see if cursor's off top
  407.     bge    sk0_as        * jump if not off the top
  408. lp0_as:
  409.     subq.l    #1,a0        * start backing off
  410.     cmp.l    b_buf(a5),a0    * don't go under start of file
  411.     beq    sk1_as        * jump if at start of file
  412.     cmp.b    #10,(a0)    * look for newline
  413.     bne    lp0_as        * not newline, try again
  414.     addq.l    #1,a0        * ok, move past newline
  415. sk1_as:
  416.     cmp.l    b_buf(a5),a0    * one last check for nasties
  417.     bge    sk5_as        * no nasties
  418.     move.l    b_buf(a5),a0    * start at top
  419. sk5_as:
  420.     move.l    a0,top_lef(a5)    * reset top of screen
  421.     bra    sk3_as        * exit
  422. sk0_as:
  423.     sub.l    top_lef(a5),a0    * A0 is now chars-to-cursor
  424.     move.l    a0,d0        * we need count in data register
  425.     move.l    top_lef(a5),a0    * A0 is where we start looking
  426.     clr.w    d1        * d1 will be newline count
  427.     bra    sk2_as        * do loop test before check
  428. lp1_as:
  429.     cmp.b    #10,(a0)+    * look for newlines
  430.     bne    sk2_as        * if not newline, don't care
  431.     addq.w    #1,d1        * if newline, increment count
  432. sk2_as:
  433.     dbra    d0,lp1_as    * loop test
  434.     sub.w    w_rows(a5),d1    * see if more newlines than rows
  435.     blt    sk3_as        * if not, we're ok
  436.     move.l    top_lef(a5),a0    * get starting point
  437. lp3_as:
  438.     cmp.b    #10,(a0)+    * we need to skip newlines
  439.     bne    lp3_as        * if not newline, we don't care
  440. sk4_as:
  441.     dbra    d1,lp3_as    * loop for (d1+1) newlines
  442.     move.l    a0,top_lef(a5)    * save new top left corner
  443. sk3_as:
  444.     rts
  445.  
  446.     end
  447.